`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:41:04 11/28/2011 
// Design Name: 
// Module Name:    packet_capture 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module stream_capture(
  input         CLK,
  input         RST,
  
  input   [47:0]  TIME,
  input           TRIG,
  input           VALID,
  input   [127:0] DATA,
  input   [3:0]   STRB,
  input           LAST,
  
//Register Port
  input           RP_EN,
  input   [3:0]   RP_WE,
  input   [3:0]   RP_A,
  input   [31:0]  RP_DI,
  output  [31:0]  RP_DO,
  output          RP_RDY,

  output  [0:0]   M_AWID,  
  output  [31:0]  M_AWADDR,
  output  [7:0]   M_AWLEN,
  output  [2:0]   M_AWSIZE,
  output  [1:0]   M_AWBURST,
  output          M_AWVALID,
  input           M_AWREADY,
  output  [127:0] M_WDATA,
  output  [15:0]  M_WSTRB,
  output          M_WLAST,
  output          M_WVALID,
  input           M_WREADY,
  input   [0:0]   M_BID,
  input   [1:0]   M_BRESP,
  input           M_BVALID,
  output          M_BREADY
);

  wire        axis_en = (RP_A[3] == 1'b0) ? RP_EN : 1'b0;
  wire [3:0]  axis_we = (RP_A[3] == 1'b0) ? RP_WE : 4'b0;
  wire [2:0]  axis_a = RP_A[2:0];
  wire [31:0] axis_wd = RP_DI;
  wire [31:0] axis_rd;
  wire        axis_rdy;
  
  wire        my_en = (RP_A[3] == 1'b1) ? RP_EN : 1'b0;
  wire [3:0]  my_we = (RP_A[3] == 1'b1) ? RP_WE : 4'b0;
  wire [2:0]  my_a = RP_A[2:0];
  wire [31:0] my_wd = RP_DI;
  reg  [31:0] my_rd;
  reg         my_rdy;
  
  assign RP_DO =  (RP_A[3] == 1'b0) ? axis_rd :
                  (RP_A[3] == 1'b1) ? my_rd : 32'b0;
  assign RP_RDY = axis_rdy || my_rdy;
  
  wire          fifo_rst;
  wire [180:0]  fifo_din;
  wire [180:0]  fifo_dout;
  wire          fifo_wr_en;
  wire          fifo_rd_en;
  wire          fifo_full;
  wire          fifo_empty;
  wire          fifo_overflow;
  
  wire          axis_tvalid;
  wire          axis_tready;
  wire [127:0]  axis_tdata;
  wire [3:0]    axis_tstrb;
  wire [47:0]   axis_tuser;
  wire          axis_tlast;
  
  reg [47:0]    TrigTS;
  reg [31:0]    PostTrigCount;
  reg [31:0]    PostTrigCounter;
  reg           Triggered;
  reg           Start;
  reg           Stop;
  reg           Recording;
  reg           ResetFifo;
  reg           FifoOverFlowError;
  wire          PostTrigCountout;
  
  always @(posedge CLK)
  begin
    if (RST || my_rdy)
      my_rdy <= 1'b0;
    else if(my_en)
      my_rdy <= 1'b1;
  end

  always @(posedge CLK)
  begin
    if (RST)
    begin
      ResetFifo <= 1'b0;
    end
    else if (my_en)
    begin
      case (my_a)
        3'h0: 
          begin
            my_rd <= {11'h0, FifoOverFlowError, fifo_full, fifo_empty, Triggered, Recording, 13'h0, ResetFifo, Stop, Start};
            if (my_we[0]) ResetFifo <= my_wd[2];
          end
        3'h1:
          begin
            my_rd <= PostTrigCounter;
            if (my_we[0]) PostTrigCount[7:0] <= my_wd[7:0];
            if (my_we[1]) PostTrigCount[15:8] <= my_wd[15:8];
            if (my_we[2]) PostTrigCount[23:16] <= my_wd[23:16];
            if (my_we[3]) PostTrigCount[31:24] <= my_wd[31:24];
          end
        3'h2: my_rd <= TrigTS[31:0];
        3'h3: my_rd <= {16'h0, TrigTS[47:32]};
        default: my_rd <= 32'h0;
      endcase
    end
    
  end
  
  always @(posedge CLK)
  begin
    if (RST)
    begin
      Start <= 0;
      Stop <= 0;
    end
    else
    begin
      Start <= my_en && my_we[0] && my_wd[0];
      Stop <= my_en && my_we[0] && my_wd[1];
    end
  end
  
  always @(posedge CLK)
  begin
    if (RST)
      Recording <= 1'b0;
    else if (Recording)
    begin
      if (Stop || PostTrigCountout) Recording <= 1'b0;
    end
    else
    begin
      if (Start) Recording <= 1'b1;
    end
  end
  
  always @(posedge CLK)
  begin
    if (Start)
      Triggered <= 1'b0;
    else if(TRIG)
      Triggered <= 1'b1;
  end
  
  always @(posedge CLK)
  begin
    if (Start)
      TrigTS <= 48'h0;
    else if (Recording && !Triggered && TRIG)
      TrigTS <= TIME;
  end
  
  always @(posedge CLK)
  begin
    if (Recording && !Triggered && TRIG)
      PostTrigCounter <= PostTrigCount;
    else if (Recording && Triggered && VALID)
    begin
      if (LAST)
        PostTrigCounter <= PostTrigCounter - 2;
      else
        PostTrigCounter <= PostTrigCounter - 1;
    end
  end
  
  assign PostTrigCountout = PostTrigCounter[31];
  
  assign fifo_rst = ResetFifo;
  assign fifo_din = {LAST, TIME, STRB, DATA};
  assign {axis_tlast, axis_tuser, axis_tstrb, axis_tdata} = fifo_dout;
  assign fifo_wr_en = Recording && VALID;
  assign fifo_rd_en = axis_tready;
  assign axis_tvalid = !fifo_empty;
  
  fwft_fifo_181
  fifo(
    .clk      (CLK),
    .rst      (fifo_rst),
    .din      (fifo_din),
    .wr_en    (fifo_wr_en),
    .rd_en    (fifo_rd_en),
    .dout     (fifo_dout), 
    .full     (fifo_full), 
    .overflow (fifo_overflow),
    .empty    (fifo_empty)
  );
  
  axis_recorder 
  axis_rec(
    .CLK            (CLK),
    .RST            (RST),
    
    .RP_EN          (axis_en),
    .RP_WE          (axis_we),
    .RP_A           (axis_a),
    .RP_DI          (axis_wd),
    .RP_DO          (axis_rd),
    .RP_RDY         (axis_rdy),

    .S_TVALID       (axis_tvalid ),
    .S_TREADY       (axis_tready ),
    .S_TDATA        (axis_tdata  ),
    .S_TSTRB        (axis_tstrb  ),
    .S_TUSER        (axis_tuser  ),
    .S_TLAST        (axis_tlast  ),

    .M_AWID         (M_AWID      ),
    .M_AWADDR       (M_AWADDR    ),
    .M_AWLEN        (M_AWLEN     ),
    .M_AWSIZE       (M_AWSIZE    ),
    .M_AWBURST      (M_AWBURST   ),
    .M_AWVALID      (M_AWVALID   ),
    .M_AWREADY      (M_AWREADY   ),
    .M_WDATA        (M_WDATA     ),
    .M_WSTRB        (M_WSTRB     ),
    .M_WLAST        (M_WLAST     ),
    .M_WVALID       (M_WVALID    ),
    .M_WREADY       (M_WREADY    ),
    .M_BID          (M_BID       ),
    .M_BRESP        (M_BRESP     ),
    .M_BVALID       (M_BVALID    ),
    .M_BREADY       (M_BREADY    )
  );    
endmodule
